
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <dirent.h>
#include <string.h>
#include <unistd.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <signal.h>
#include <fcntl.h>
#include <pthread.h>


#include <opencv2/opencv.hpp>

#define VK_LBUTTON	0x01	//输入笔点击
#define VK_RBUTTON	0x02	//鼠标右键
#define VK_CANCEL	0x03	//Control-Break处理
#define VK_MBUTTON	0x04	//鼠标中间键
#define VK_BACK	0x08	//Backspace键
#define VK_TAB	0x09	//Tab键
#define VK_CLEAR	0x0C	//Clear键
#define VK_RETURN	0x0D	//Enter键
#define VK_SHIFT	0x10	//Shift键
#define VK_CONTROL	0x11	//Ctrl键
#define VK_MENU	0x12	//Alt键
#define VK_PAUSE	0x13	 
#define VK_CAPITAL	0x14	//Caps lock键
#define VK_KANA	0x15	 
#define VK_HANGEUL	0x15	 
#define VK_HANGUL	0x15	 
#define VK_JUNJA	0x17	 
#define VK_FINAL	0x18	 
#define VK_HANJA	0x19	 
#define VK_KANJI	0x19	 
#define VK_ESCAPE	0x1B	//Escape键
#define VK_CONVERT	0x1C	 
#define VK_NONCONVERT	0x1D	 
#define VK_ACCEPT	0x1E	 
#define VK_MODECHANGE	0x1F	 
#define VK_SPACE	0x20	//空格键
#define VK_PRIOR	0x21	//Page up键
#define VK_NEXT	0x22	//Page down键
#define VK_END	0x23	//End键
#define VK_HOME	0x24	//Home键
#define VK_LEFT	0x25	//左箭头键
#define VK_UP	0x26	//上箭头键
#define VK_RIGHT	0x27	//右箭头键
#define VK_DOWN	0x28	//下箭头键
#define VK_SELECT	0x29	//Select键
#define VK_PRINT	0x2A	 
#define VK_EXECUTE	0x2B	//Execute键
#define VK_SNAPSHOT	0x2C	//Print screen键
#define VK_INSERT	0x2D	//Insert键
#define VK_DELETE	0x2E	//Delete键
#define VK_HELP	0x2F	//Help键
//#define VK_0 - VK_9	0x30 - 0x39	 
#define VK_A	0x41	 
#define VK_B	0x42	 
#define VK_C	0x43	 
#define VK_D	0x44	 
#define VK_E	0x45	 
#define VK_F	0x46	 
#define VK_G	0x47	 
#define VK_H	0x48	 
#define VK_I	0x49	 
#define VK_J	0x4A	 
#define VK_K	0x4B	 
#define VK_L	0x4C	 
#define VK_M	0x4D	 
#define VK_N	0x4E	 
#define VK_O	0x4F	 
#define VK_P	0x50	 
#define VK_Q	0x51	 
#define VK_R	0x52	 
#define VK_S	0x53	 
#define VK_T	0x54	 
#define VK_U	0x55	 
#define VK_V	0x56	 
#define VK_W	0x57	 
#define VK_X	0x58	 
#define VK_Y	0x59	 
#define VK_Z	0x5A	 
#define VK_LWIN	0x5B	 
#define VK_RWIN	0x5C	 
#define VK_APPS	0x5D	 
//#define VK_NUMPAD0 - K_NUMPAD9	0x60 - 0x69	数字小键盘上的0 - 9
#define VK_MULTIPLY	0x6A	//数字小键盘上的*
#define VK_ADD	0x6B	//数字小键盘上的+
#define VK_SEPARATOR	0x6C	//分隔符键
#define VK_SUBTRACT	0x6D	//数字小键盘上的-
#define VK_DECIMAL	0x6E	//数字小键盘上的.
#define VK_DIVIDE	0x6F	//数字小键盘上的/
#define VK_F1	0x70	 
#define VK_F2	0x71	 
#define VK_F3	0x72	 
#define VK_F4	0x73	 
#define VK_F5	0x74	 
#define VK_F6	0x75	 
#define VK_F7	0x76	 
#define VK_F8	0x77	 
#define VK_F9	0x78	 
#define VK_F10	0x79	 
#define VK_F11	0x7A	 
#define VK_F12	0x7B	 
//#define VK_F13 - VK_F24	0x7C - 0x87	 
#define VK_NUMLOCK	0x90	 
#define VK_SCROLL	0x91	//Scroll Lock
//#define VK_L* & VK_R* - left and right Alt, Ctrl and Shift virtual keys.	 	Used only as parameters to GetAsyncKeyState() and GetKeyState().No other API or message will distinguish left and right keys in this way.
#define VK_LSHIFT	0xA0	 
#define VK_RSHIFT	0xA1	 
#define VK_LCONTROL	0xA2	 
#define VK_RCONTROL	0xA3	 
#define VK_LMENU	0xA4	//左Alt键
#define VK_RMENU	0xA5	//右Alt键
#define VK_PROCESSKEY	0xE5	//WINVER >= 0x0400
#define VK_ATTN	0xF6	 
#define VK_CRSEL	0xF7	 
#define VK_EXSEL	0xF8	 
#define VK_EREOF	0xF9	 
#define VK_PLAY	0xFA	 
#define VK_ZOOM	0xFB	 
#define VK_NONAME	0xFC	 
#define VK_PA1	0xFD	 
#define VK_OEM_CLEAR	0xFE	 
#define VK_OEM_1	0xBA	//;:      US standard keyboard
#define K_OEM_PLUS	0xBB	//=+     any country/region
#define VK_OEM_COMMA	0xBC	//,<     any country/region
#define VK_OEM_MINUS	0xBD	//-_     any country/region
#define VK_OEM_PERIOD	0xBE	//>.     any country/region
#define VK_OEM_2	0xBF	///?     US standard keyboard
#define VK_OEM_3	0xC0	//`~     US standard keyboard
//0xC1 - 0xD7	保留
//0xD8 - 0xDA	未赋值
#define VK_OEM_4	0xDB	//[{'     US standard keyboard
#define VK_OEM_5	0xDC	//\|     US standard keyboard
#define VK_OEM_6	0xDD	//]}     US standard keyboard
#define VK_OEM_7	0xDE	//'"     US standard keyboard



#define  SCAN_PICTURE_PATH      ("/media/root/4A58E91358E8FF17/")

using namespace cv;

static unsigned long total_picture_file = 0;

static char* picture_data_buff = NULL;

static char  picture_path[1024];

static int   img_show_time  = 10;
static int   img_show_mode  = 0;
static int   img_show_state = 0;
static int   img_time_cnt   = 0;
static int   img_timeout_flag   = 1;
static int   img_manual_skip    = 0;


static  pthread_t img_thread = -1;

int Show_picture(const char *filename);
void img_resource_free(void);

int Show_picture(const char *filename)
{
	
	Mat pic;
	Mat dst;

	pic = imread(filename);
	
	if(pic.empty()) 
	{
		return -1;
	}
	
	namedWindow("pic", WINDOW_NORMAL);

	setWindowProperty("pic", WND_PROP_FULLSCREEN,WINDOW_FULLSCREEN);

	if (pic.rows > pic.cols)
	{
		rotate(pic, dst, ROTATE_90_CLOCKWISE);
		imshow("pic", dst);
	}
	else 
	{
		imshow("pic",pic);
	}

	return 0;

}


int  Is_file_exist(const char* filename)
{

	FILE* fs = NULL;

	fs=fopen(filename,"r");
	if (!fs)
	{
		return 0;
	}

	fclose(fs);
	fs = NULL;

	return 1;
}

int get_filename_from_txt(void)
{
	int file_len = 0;

	FILE* fs = NULL;

	char filename[1024];

	fs=fopen("./filelist.txt","rb");
	if (!fs)
	{
		return 0;
	}

    fseek(fs, 0, SEEK_END);
    file_len = ftell(fs);
    fseek(fs, 0, SEEK_SET);

	total_picture_file = file_len/1024;
	
    printf("file_len = %d\n",file_len);
    printf("file_num = %d\n",total_picture_file);

    picture_data_buff = (char *)malloc(file_len);
    if(!picture_data_buff){
        printf("malloc error\n");
        fclose(fs);
        fs = NULL;
        return 0;
    }

	fread(picture_data_buff,file_len,1,fs);

	fclose(fs);
	fs = NULL;
	

    return 0;

}


int search_picture_path( const char *path)
{
	DIR *dir;
	struct dirent *ptr;

	if ((dir = opendir(path)) == NULL)
	{
		printf("Open dir error...");
		exit(1);
	}

	while ((ptr = readdir(dir)) != NULL)
	{
		if(strcmp(ptr->d_name, ".")==0 || strcmp(ptr->d_name, "..")==0)    ///current dir OR parrent dir
			continue;
	
		switch (ptr->d_type)
		{
			case DT_REG:	
			{

				break;
			}
			case DT_DIR:	
			{
				memset(picture_path,'\0',sizeof(picture_path));
				strcpy(picture_path,path);
				strcat(picture_path,"/");
				strcat(picture_path,ptr->d_name);

				printf("picture_path=%s\n",picture_path);
				
				break;
			}
			case DT_UNKNOWN:break;
			default:break;
		}
	}

	closedir(dir);
}


static void *img_show_thread(void *arg)
{
	struct timeval timer;	

	while(1)
	{
		timer.tv_sec  = 1;  // 定时1秒
		timer.tv_usec = 0;  
		
		switch(select(0, NULL, NULL, NULL, &timer)) {
		case -1:  // 错误
			printf("Error!\n");
			break;
		case 0: //超时
			img_time_cnt ++;
			break;
		default:
			printf("default\n");
			break;
		}
		if(img_time_cnt >= img_show_time){
			img_time_cnt = 0;
			img_timeout_flag = 1;
		}
	}
}

int main(int argc, char *argv[])
{
	int i = 0;
	int  index    = 0;
	char filename[1024];
	char filetemp[1024];
	char filetemp2[1024];
	char * used_buff = NULL;

	time_t timep;   
	struct tm *tm_p;   

	int s_rand = 0;
	int key_num = 0;
 

	printf("argc=%d\n",argc);
	
	for(i=0;i<argc;i++)
	{
		printf("argv[%d]=%s\n",i,argv[i]);
	}

	if(argc>=2){
		switch(*argv[1]){
		case '0':{
			img_show_mode = 0;
			break;
		}
		case '1':{
			img_show_mode = 1;
			break;
		}		
		default:break;
		}
	}

	if(argc>=3){
		printf("argv2=%d\n",*argv[2]);
		switch(*argv[2]){
		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':{
			img_show_time = (*argv[2] - 48)*3 + 5;
			break;
		}		
		default:break;
		}
	}

	printf("img_show_time=%d\n",img_show_time);
	printf("img_show_mode=%d\n",img_show_mode);
	
	search_picture_path(SCAN_PICTURE_PATH);

	time(&timep);   
	tm_p = localtime(&timep);	
	timep = mktime(tm_p);
    printf("timep = %d\n", timep);
	
	RNG rng(timep);
	
	get_filename_from_txt();

	pthread_create(&img_thread, NULL, img_show_thread, NULL);


	while(1)
	{
		time(&timep);   
		tm_p = localtime(&timep);	
		timep = mktime(tm_p);		
		rng(timep);

		key_num = waitKey(10);

		#if 0
		if(key_num != (-1))
			printf("key_num = %d\n", key_num);
		//printf("img_show_state = %d\n", img_show_state);
		#endif	
		
		if(key_num == VK_ESCAPE){
			img_resource_free();
			exit(-1);
		}else if(key_num == VK_SPACE){
			if(img_show_state){
				img_show_state   = 0;
				img_timeout_flag = 1;
			}else{
				img_show_state = 1;
			}
		}else if((key_num == 84)||(key_num == 83)){
			img_timeout_flag = 1;
			img_manual_skip  = 1;
		}else if((key_num == 82)||(key_num == 81)){
			img_timeout_flag = 1;
			img_manual_skip  = 1;
		}else{

		}
		

		if(img_show_state){
			img_time_cnt     = 0;

			if(img_manual_skip){
				img_manual_skip = 0;
			}else{
				img_timeout_flag = 0;
				continue;
			}
		}else{

		}


		if(img_timeout_flag){

			switch(img_show_mode){
			case 0:{
				index = rng.uniform(1,total_picture_file);
				break;
			}
			case 1:{
				index ++;
				break;
			}
			default:break;
			}

			//printf("img_show_mode = %d\n", img_show_mode);
			//printf("index = %d\n", index);
			
			if(index >= total_picture_file)
				index = 0; 
			
			used_buff = picture_data_buff + index*1024;
			
			memset(filetemp,0,1024);
			memcpy(filetemp,used_buff,1024);
			//printf("filetemp = %s\n",filetemp);
			
			strcpy(filename,picture_path);
			strcat(filename,"/");
			strcat(filename,filetemp);
			
			printf("filename = %s\n",filename);
			
			Show_picture(filename);

			img_timeout_flag = 0;
		}
	}
	

	return 0;


}




void img_resource_free(void)
{
	if(picture_data_buff){
		free(picture_data_buff);
		picture_data_buff = NULL;
	}


}






